package memorphic.xpath {

	import flexunit.framework.TestCase;
	import flexunit.framework.TestSuite;
	import memorphic.xpath.fixtures.XMLData;
	import flexunit.framework.TestResult;
	import memorphic.xpath.model.XPathContext;
	
	
	public class XPathTests extends TestCase {
		
		
			TestResult.rethrowErrors = true;
		
	    public function XPathTests( methodName:String = null) {
			super( methodName );
        }

		
		public override function setUp():void
		{
			XPathQuery.defaultContext = new XPathContext();
		}
		
		public override function tearDown():void
		{
			
		}


		
		public function testSimpleSteps():void
		{
			
			var data:XML = XMLData.foodMenuXML;
			// all of these queries should have the same results
			var paths:Array = ["breakfast-menu/food/name",
							"breakfast-menu//name",
							"/breakfast-menu/food/name",
							"/breakfast-menu/food//name",
							"/breakfast-menu//name",
							"//food/name",
							"//food//name",
							"//name",
							"/child::breakfast-menu/child::food/child::name",
							"/breakfast-menu/food/parent::node()/food/name",
							"/breakfast-menu/food/../food/name",
							"descendant::breakfast-menu/food/name",
							"descendant-or-self::node()/name[local-name(.)='name']",
							"/descendant-or-self::node()/name[string(local-name(.))='name']",
							"/descendant-or-self::node()/name[local-name(../child::node()) = 'name']",
							"//*/name",
							"*//name",
							"*/food/name",
							"*/*/name"];
			var result:XMLList;
			var n:int = paths.length;
			var expected:String = data.food.name.toXMLString();
			for(var i:int=0; i<n; i++){

				result = XPathQuery.select(data, paths[i]);
				assertTrue(i+" result should be XMLList", result is XMLList);
				assertEquals(i+" should select 5 items", 5, result.length());
				assertEquals(i+" should select a <name> node", "name", result[0].name());
				assertEquals(i+" should match the expected result", expected, result.toXMLString());
			}
		}
		
		
		public function testPosition():void
		{
			var data:XML = XMLData.foodMenuXML;
			
			var paths:Array = [
							"breakfast-menu/food[2]/name",
							"breakfast-menu/food[7-5]/name",
							"breakfast-menu/food[(7-5)]/name",
							"breakfast-menu/food[(2+2)-(5 *3-13)]/name",
							"breakfast-menu/food[position() = 2]/name",
							"breakfast-menu/food[position()=2]/name",
							"breakfast-menu/food[last()-3]/name",
							"breakfast-menu/food/name[string() = 'Strawberry Belgian Waffles']"];
			
			var result:XMLList;
			var n:int = paths.length;
			var expected:String = data.food.name.toXMLString();
			for(var i:int=0; i<n; i++){
				result = XPathQuery.select(data, paths[i]);
				assertEquals(i+" should be only one element", 1, result.length());
				assertEquals(i+" check name", "Strawberry Belgian Waffles", result.toString());
				assertEquals(i+" should be second element", data.food.name[1], result[0]);
				
				
			}
			
		}
		
		
		public function testNamespaces():void
		{
			var data:XML = XMLData.adobeHomeXHTML;
			
			var xpath:XPathQuery = new XPathQuery("//xhtml:head");
			xpath.context.namespaces.xhtml = "http://www.w3.org/1999/xhtml";
			var result:XMLList = xpath.exec(data);
			
			assertEquals("only select one node", 1, result.length());
			assertEquals("local name should be <head>", "head", result[0].localName());
			
		}
		
		public function testWildCardNamespace():void
		{
			var data:XML = XMLData.adobeHomeXHTML;
			
			var xpath:XPathQuery = new XPathQuery("//*:head");
			var result:XMLList = xpath.exec(data);
			
			assertEquals("only select one node", 1, result.length());
			assertEquals("local name should be <head>", "head", result[0].localName());
			
		}
		
		public function testOpenAllNamespaces():void
		{
			var data:XML = XMLData.adobeHomeXHTML;
			
			var xpath:XPathQuery = new XPathQuery("//head");
			var result:XMLList = xpath.exec(data);
			
			assertEquals("Shouldn't match anything - I didn't map the namespace", 0, result.length());
			
			xpath.context.openAllNamespaces = true
			var result2:XMLList = xpath.exec(data);
			assertEquals("only select one node", 1, result2.length());
			assertEquals("local name should be <head>", "head", result2[0].localName());
			
		}
		
		
		public function testVariables():void
		{
		}


		public function testFilterExpr():void
		{
			
			var data:XML = XMLData.foodMenuXML;
			var xpath:XPathQuery = new XPathQuery( "breakfast-menu/food[secondNode(.)[1]=.]/name");
			xpath.context.functions.secondNode = function (context:XPathContext, nodeset:XMLList):XMLList
			{
				if(context.position() == 2){
					return XMLList(nodeset[0]);
				}else{
					return new XMLList();
				}
			}
			var result:XMLList = xpath.exec(data);
			assertEquals("only select one node", 1, result.length());
			assertEquals("check name", "Strawberry Belgian Waffles", result.toString());
		}
	}
		
}